#include <iostream>
#include <string>
#include <strings.h>
#include <string.h>
#include <memory>
#include <jsoncpp/json/json.h>

// 序列化 json对象
bool Serialize(const Json::Value &val, std::string &body)
{
    std::stringstream ss;

    // 构建 StreamWriterBuilder 工厂类, 生产 StreamWriter 对象
    Json::StreamWriterBuilder swb;
    swb["emitUTF8"] = true;

    // Json::StreamWriter* sw = swb.newStreamWriter();
    std::shared_ptr<Json::StreamWriter> sw(swb.newStreamWriter());

    bool ret = sw->write(val, &ss);
    if (ret != 0)
    {
        std::cerr << "Serialize error\n";
        return false;
    }

    body = ss.str();
    return true;
}

// 反序列化
bool UnSerialize(const std::string &in_message, Json::Value &val)
{
    Json::CharReaderBuilder crb;

    std::shared_ptr<Json::CharReader> cr(crb.newCharReader());

    std::string errs;
    bool ret = cr->parse(in_message.c_str(), in_message.c_str() + in_message.size(), &val, &errs);

    return true;
}

int main()
{
    Json::Value student;
    const char *name = "张三";
    int age = 18;
    const char *sex = "男";
    float score[3] = {99, 99.5, 100};

    student["姓名"] = name;
    student["年龄"] = age;
    student["性别"] = sex;

    student["成绩"].append(score[0]);
    student["成绩"].append(score[1]);
    student["成绩"].append(score[2]);

    Json::Value fav;
    fav["书籍"] = "三体";
    fav["运动"] = "跑步";

    student["爱好"] = fav;

    std::string out_message;

    // Json::StreamWriterBuilder jswBuilder;
    // jswBuilder["emitUTF8"]=true;
    // std::unique_ptr<Json::StreamWriter>jsWriter(jswBuilder.newStreamWriter());

    // std::ostringstream os;
    // jsWriter->write(student, &os);
    // cout << os.str() << endl;
    // bool ret = SerializeJson(student, out_message);

    bool ret = Serialize(student, out_message);
    (void)ret;

    std::cout << out_message << std::endl;

    Json::Value get_student;
    UnSerialize(out_message, get_student);

    std::cout << "姓名: " << get_student["姓名"].asString()
              << " "
              << "年龄: " << get_student["年龄"].asInt()
              << " "
              << "性别: " << get_student["性别"].asString()
              << std::endl;
    int size = get_student["成绩"].size();
    for (int i = 0; i < size; i++)
        std::cout << "成绩: " << get_student["成绩"][i].asFloat() << std::endl;

    return 0;
}